package com.mdp.tpa.wechat.service;

import com.mdp.tpa.wechat.HttpRequestUtil;
import com.mdp.tpa.wechat.api.cache.Oauth2CodeCache;
import com.mdp.tpa.wechat.api.cache.Oauth2TokenCache;
import com.mdp.tpa.wechat.config.AppProperties;
import com.mdp.tpa.wechat.config.WxopenProperties;
import com.mdp.tpa.wechat.config.WxpubProperties;
import com.mdp.tpa.wechat.service.cache.DefaultOauth2CodeCacheService;
import com.mdp.tpa.wechat.service.cache.DefaultOauth2TokenCacheService;
import com.mdp.tpa.wechat.api.ApiUrls;
import com.mdp.tpa.wechat.api.Oauth2AccessTokenService;
import com.mdp.tpa.wechat.entity.Oauth2AccessToken;
import com.mdp.core.api.Cache;
import com.mdp.core.err.BizException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service
public class Oauth2AccessTokenServiceImpl implements Oauth2AccessTokenService {
	 
	Log log=LogFactory.getLog(Oauth2AccessTokenServiceImpl.class); 
	 
	DefaultOauth2TokenCacheService defaultTokenCache=new DefaultOauth2TokenCacheService();
	DefaultOauth2CodeCacheService defaultCodeCache=new DefaultOauth2CodeCacheService();
	@Autowired(required=false)
	Oauth2TokenCache oauth2AccessTokenCache=defaultTokenCache;
	@Autowired(required=false)
	Oauth2CodeCache oauth2CodeCache=defaultCodeCache;
	
	@Value("${mdp.wxapi.enabled-load-access-token:true}")
	boolean enabledLoadAccessToken=true;
	  
	@Override
	public Oauth2AccessToken getSnsOauth2AccessToken(AppProperties appProperties, Oauth2AccessToken oau2AccessToken) {
		String accessToken = oau2AccessToken.getAccessToken();
		Oauth2AccessToken snsAccessToken=oauth2AccessTokenCache.get(accessToken);
		if(snsAccessToken==null){  
			return null;
		}else{
			Date d=new Date();
			long refreshTimes=snsAccessToken.getRefreshDate().getTime();
			long createTimes=snsAccessToken.getCreateDate().getTime();
			long nowTimes= d.getTime();
			if(nowTimes-(createTimes+2592000000.0)<=9000000){//还差9000秒就要过30天了,或者已经过了30天，作废
				oauth2AccessTokenCache.remove(accessToken);
				snsAccessToken=null;  
				return snsAccessToken;
			}else {
				if(nowTimes-(refreshTimes+(snsAccessToken.getExpiresIn()*1000))<3000000){//还差3000秒过期，即过期
					try{

						Oauth2AccessToken snsAccessTokenNew=refreshSnsOauth2AccessToken(appProperties.getAppid(),snsAccessToken.getRefreshToken());
						snsAccessTokenNew.setCreateDate(snsAccessToken.getCreateDate()); 
						snsAccessToken=snsAccessTokenNew;
 						oauth2AccessTokenCache.put(snsAccessTokenNew.getAccessToken(), snsAccessTokenNew);
					}catch (Exception e) { 
	 					snsAccessToken= null; 
					} 
					oauth2AccessTokenCache.remove(accessToken);
					return snsAccessToken;
				}else{
					return snsAccessToken;
				} 
			}
		}  
	}
 

	@Override
	public Oauth2AccessToken getSnsOauth2AccessToken(AppProperties appProperties, String code) {
		Oauth2AccessToken snsAccessToken=oauth2CodeCache.get(code); 
		
			if(snsAccessToken==null){
				Map<String, Object> result= HttpRequestUtil.sendGetJson(String.format(ApiUrls.SNS_ACCESS_TOKEN_BY_CODE, appProperties.getAppid(), appProperties.getAppSecret(),code), null);
				if(!result.containsKey("access_token")){
					log.error(result); 
					return null;
				}
				Oauth2AccessToken token=new Oauth2AccessToken();
				token.setAccessToken((String) result.get("access_token"));
				token.setExpiresIn((Integer) result.get("expires_in"));
				token.setOpenid((String) result.get("openid"));
				token.setScope((String) result.get("scope"));
				token.setRefreshToken((String) result.get("refresh_token"));
				token.setUnionid((String) result.get("unionid"));
				token.setCreateDate(new Date());
				token.setRefreshDate(new Date());
				snsAccessToken=token;
				oauth2AccessTokenCache.put(snsAccessToken.getAccessToken(), snsAccessToken);
				oauth2CodeCache.put(code, snsAccessToken);
				Map<String,String> at=new HashMap<>();
				at.put(appProperties.getAppid(), snsAccessToken.getAccessToken());
				return snsAccessToken;
			}else {
				Date d=new Date(); 
				long createTimes=snsAccessToken.getCreateDate().getTime();
				long nowTimes= d.getTime();
				if((nowTimes-createTimes)>300000){//如果已经过去5分钟，该code无效
					oauth2CodeCache.remove(code);
					return null;
				}else{
					return snsAccessToken;
				} 
			} 
			
	}

  
	
	@Override
	public Oauth2AccessToken refreshSnsOauth2AccessToken(String appid, String refreshToken) { 
		Map<String,Object> map=new HashMap<>();
		map.put("appid",appid);
		map.put("refreshToken",refreshToken); 
		Map<String, Object> result=HttpRequestUtil.sendGetJson(String.format(ApiUrls.SNS_ACCESS_TOKEN_REFRESH, appid,refreshToken), null); 
		if(!result.containsKey("access_token")){
			log.error(result);
			log.error("获取access_token出错，将再尝试一次向微信获取access_token");
			result=HttpRequestUtil.sendGetJson(String.format(ApiUrls.SNS_ACCESS_TOKEN_REFRESH, appid,refreshToken), null); 
			
		}
		if(!result.containsKey("access_token")){
			throw new BizException(""+ result.get("errcode"), (String) result.get("errmsg"));
		}
		Oauth2AccessToken token=new Oauth2AccessToken();
		token.setAccessToken((String) result.get("access_token"));
		token.setExpiresIn((Integer) result.get("expires_in"));
		token.setOpenid((String) result.get("openid"));
		token.setScope((String) result.get("scope"));
		token.setRefreshToken((String) result.get("refresh_token"));
		token.setUnionid((String) result.get("unionid"));
		token.setRefreshDate(new Date());
		return token;
	}


	public Cache getOauth2AccessTokenCache() {
		return oauth2AccessTokenCache;
	}


	public void setOauth2AccessTokenCache(Oauth2TokenCache oauth2AccessTokenCache) {
		this.oauth2AccessTokenCache = oauth2AccessTokenCache;
	}


	public Cache getOauth2CodeCache() {
		return oauth2CodeCache;
	}


	public void setOauth2CodeCache(Oauth2CodeCache oauth2CodeCache) {
		this.oauth2CodeCache = oauth2CodeCache;
	}

 
}
